# coding:utf-8
import os
import urllib
import uuid
import json
import random
from datetime import date

from flask import request, current_app
from flask_restful import Api, Resource

from app.extensions import im_sync_proxy, db
from app.api.codes import PARAMS_ILLEGAL
from app.api_v2.codes import USER_NOT_EXISTED, BID_POINT_NOT_ENOUGH, \
    TRANSFER_TO_SELF
from app.api_v2.constant import PER_PAGE, IM_NOTIFY_KEY
from app.op.constant import ParticStatus, BidCostType
from common.constant import BidQueueStatus
from common.utils import ImageUtils, QiNiu
from .views import Response, AppAuthResource
from .im_schemas import im_message_create_schema, im_messages_schema, \
    im_notify_schema, im_group_schema, time_line_msg_schema, transfer_schema
from app.op.models import IMMessage, Follow, Partic, BidCostRecord, BidUserQueue
from common.im_util import im_client, SYS_IM_NOTIFY_FROM
from app.op.models import User

api = Api()


@api.resource('/im/messages')
class IMMessageResource(AppAuthResource):
    """
    created by chenhj at 2017/11/22

    """

    def get(self):
        """
        获取im信息列表
        :return:
        """
        data, errors = im_group_schema.load(request.args)
        per_page = request.args.get('message_count', type=int, default=PER_PAGE)
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0])
            )
        query = IMMessage.message_list(data['group_id'])

        total = query.count()
        created_at = data.get('created_at')
        if created_at:
            query = query.filter(IMMessage.created_at < created_at)

        messages = query.limit(per_page).all()

        for message in messages:
            if message.im_to == str(self.user.id) and not message.read_status:
                message.read_status = True

        items, errors = im_messages_schema.dump(messages)
        return Response(
            body={
                'list': items,
                'total': total
            }
        )

    def post(self):
        """
        created by chenhj at 2017/11/22
        存储im信息
        """
        data, errors = im_message_create_schema.load(request.get_json())
        if 'message_list' not in data:
            return Response(
                PARAMS_ILLEGAL.new_format_msg('缺少MESSAGE_LIST字段信息')
            )
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(self.nested_error(errors))
            )
        # 保存的消息为已读消息
        for each in data['message_list']:
            # FIXME by chenhj at 2018/5/10 暂时这么fix下,后面ios上线版本后删除
            if each['created_at'] < 1000000000000:
                each['created_at'] = each['created_at'] * 1000
            IMMessage.create(
                **each
            )
        return Response()

    def nested_error(self, errors):
        msg = ''
        if isinstance(errors, dict):
            msg = list(errors.values())
        if isinstance(errors, list):
            if len(errors) > 0:
                msg = errors[0]
        if isinstance(msg, str):
            return msg
        return self.nested_error(msg)


@api.resource('/im/file')
class IMFileResource(AppAuthResource):
    """
    created by chenhj at 2017/8/21
    以文件形式上传im文件
    """

    def post(self):
        """
        created by chenhj at 2017/11/22
        如果上传的是图片的话，保存缩略图
        """
        file = request.files['file']
        ext = file.filename.split('.')[-1]
        path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), '../api/img/im'
        )

        file_name = uuid.uuid4().hex
        filename = '{filename}.{format}'.format(
            format=ext,
            filename=file_name
        )
        file_path = os.path.join(path, filename)
        file.save(file_path)

        host = os.environ.get('img_host')
        url = urllib.parse.urljoin(host, 'im/{}'.format(filename))
        thumbnail_url = ''
        if ImageUtils.is_image_type(ext):
            try:
                thumbnail = ImageUtils.resize(file_path)
                thumbnail_filename = '{filename}_thumbnail.{format}'.format(
                    format=ext,
                    filename=file_name
                )
                thumbnail.save(os.path.join(path, thumbnail_filename))
                new_thumbnail_filename = '{filename}.{format}_thumbnail'.format(
                    format=ext,
                    filename=file_name
                )
                os.rename(
                    os.path.join(path, thumbnail_filename),
                    os.path.join(path, new_thumbnail_filename)
                )

                thumbnail_url = urllib.parse.urljoin(
                    host, 'im/{}'.format(new_thumbnail_filename)
                )
            except OSError as e:
                pass

        return Response(
            body={
                'url': url,
                'thumbnail_url': thumbnail_url
            }
        )

    def put(self):
        """
        create by ld_wu 2018-03-07
        上传文件到七牛
        """

        upload_file = request.files['file']
        file_name = uuid.uuid4().hex

        today = date.today()
        upload_key = '{}/{}{}/{}'.format(
            'im', today.year, today.month, file_name
        )

        url = QiNiu().upload(upload_key, upload_file.read())

        return Response(
            body={
                'url': url
            }
        )


@api.resource('/im/notifies')
class IMNotifyResource(AppAuthResource):
    """
    create by ld_wu 2017-11-23
    消息通知列表
    """

    def get(self):
        message_count = IMMessage.un_read_notify_count(self.user.id)
        msg_map = {each.group_id: each.message_count for each in message_count}
        messages = IMMessage.newest_message(msg_map.keys())

        friends = Follow.query.filter(
            Follow.followed_id == self.user.id,
            Follow.has_set_alias.is_(True)
        ).all()

        alias_mapping = {str(each.follower_id): each.alias for each in friends}

        for msg in messages:
            setattr(msg, 'un_read_count', msg_map.get(msg.group_id, 0))
            # 消息对方的id
            extend_id = (
                msg.to_id if msg.from_id == str(self.user.id) else msg.from_id
            )
            setattr(msg, 'alias', alias_mapping.get(extend_id, ''))
        return Response(
            body=im_notify_schema.dump(messages)[0]
        )

    def put(self):
        """
        更新消息为已读
        :return:
        """
        data, errors = im_group_schema.load(request.get_json())
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0])
            )
        IMMessage.mark_read_message(data['group_id'], self.user.id)
        return Response()


@api.resource('/im/time_line/notify')
class IMTimeLineNotifyResource(Resource):
    """
    create by ld_wu 2018-02-06
    发布动态通知
    """

    def post(self):
        data, errors = time_line_msg_schema.load(request.get_json())
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0])
            )
        im_client.batch_system_notify(
            SYS_IM_NOTIFY_FROM, data['to_ids'], dict(type=0, content='')
        )
        return Response()


@api.resource('/im/transfer')
class IMTransferResource(AppAuthResource):
    """
    create by ld_wu 2018-05-29
    转账接口
    """

    def post(self):
        data, errors = transfer_schema.load(request.get_json())
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(list(errors.values())[0][0])
            )
        to_id = data['to_id']
        bid_point = data['bid_point']
        if self.user.id == to_id:
            return Response(TRANSFER_TO_SELF)
        to_user = User.get_by_id(to_id)
        if not to_user or not to_user.pack:
            return Response(USER_NOT_EXISTED)

        res = self.user.transfer_bid_point(
            to_user, bid_point, data.get('remark', '')
        )
        if not res:
            return Response(
                BID_POINT_NOT_ENOUGH,
                body=dict(bid_point=self.user.pack.bid_point)
            )

        demand_ids = []
        # 如果该用户有待付费订单, 则扣取, 并更新该参与状态
        to_pay_partics = Partic.query.filter_by(
            supplier_id=to_user.id,
            status=ParticStatus.BALANCE_NOT_ENOUGH.value,
            deleted_at=0
        ).order_by(
            Partic.id
        )
        for each_partic in to_pay_partics:
            if to_user.pack.bid_point >= each_partic.offer:
                to_user.pack.bid_point -= each_partic.offer
                each_partic.status = ParticStatus.NOT_CONTACT.value
                BidCostRecord.create(
                    user_id=to_user.id,
                    cost_type=BidCostType.BID.value,
                    bid_point=each_partic.offer,
                    left_bid_point=to_user.pack.bid_point,
                    demand_id=each_partic.demand_id
                )
                demand_ids.append(each_partic.demand_id)
                # 修改外呼队列状态
                queue = BidUserQueue.query.filter(
                    BidUserQueue.partic_id == each_partic.id,
                    BidUserQueue.status == BidQueueStatus.RECHARGE
                ).first()
                if queue:
                    queue.status = BidQueueStatus.WAITING

                current_app.zone_stat_exchanger.exchange_send(json.dumps({
                    'cost_bid_point': float(each_partic.offer),
                    'cost_bid_user_id': to_user.id,
                    'war_zone_id': to_user.war_zone_id
                }))
                current_app.common_producer.send(
                    json.dumps(
                        dict(
                            backend='bid_stock_stat',
                            func='day_stat',
                            kwargs=dict(
                                stat_type='cost_bid_point',
                                stat_cnt=int(each_partic.offer),
                            )
                        )
                    )
                )

        # 转账人是否是收款人的好友
        friend = Follow.get_by_args(followed_id=to_id, follower_id=self.user.id)
        name = friend and friend.alias or self.user.nickname
        content = '[转账] 向您转账{}汇币'.format(bid_point)
        # IOS推送
        im_sync_proxy.send(json.dumps(dict(
            func='batch_sys_msg',
            kwargs=dict(
                from_id=SYS_IM_NOTIFY_FROM,
                to_ids=[to_id],
                msg=dict(
                    apsField=dict(
                        alert=dict(
                            body=content,
                            title=name
                        ),
                        chat_im=self.user.id
                    )
                ),
                push_title=name
            )
        )))

        # 极光推送
        current_app.common_producer.send(
            json.dumps(
                dict(
                    backend='jpush',
                    func='send_by_alias',
                    kwargs=dict(
                        content=content,
                        alias_list=[to_id],
                        title=name,
                        ext=dict(
                            chat_im=self.user.id,
                            msg_id='{}{}'.format(
                                to_id, random.randint(1000, 9999))    # 消息唯一标识，安卓跳转使用
                        )
                    )
                )
            )
        )

        if demand_ids:
            db.session.commit()
            for each_demand_id in demand_ids:
                Partic.clear_demand_partic_cache_data(current_app.redis, each_demand_id)
        return Response()


@api.resource('/anonymous/messages')
class AnonymousMessageResource(Resource):
    """
    create by ld_wu 2018-07-03
    """

    def post(self):
        """
        created by chenhj at 2017/11/22
        官网游客存储im信息
        """
        data, errors = im_message_create_schema.load(request.get_json())
        if 'message_list' not in data:
            return Response(
                PARAMS_ILLEGAL.new_format_msg('缺少MESSAGE_LIST字段信息')
            )
        if errors:
            return Response(
                PARAMS_ILLEGAL.new_format_msg(self.nested_error(errors))
            )
        # 保存的消息为已读消息
        for each in data['message_list']:
            # FIXME by chenhj at 2018/5/10 暂时这么fix下,后面ios上线版本后删除
            if each['created_at'] < 1000000000000:
                each['created_at'] = each['created_at'] * 1000
            IMMessage.create(
                **each
            )
        return Response()


@api.resource('/team_num')
class IMTeamNumResource(Resource):
    """
    created by chenhj at 2018/8/6

    """
    def get(self):
        """
        created by chenhj at 2018/8/6

        """
        return Response(body=dict(msg=500))
